package pers.cz.expression;

import com.jayway.jsonpath.JsonPath;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @program: StudyAntlr4
 * @description: 观察者模式观察文法解析过程，在这个过程中可以做运算操作
 * @author: Cheng Zhi
 * @create: 2023-12-14 14:12
 **/
public class JefCustomVisitor extends JefExpressionBaseVisitor<Long> {

    /**
     * 表达式中间数据寄存器
     */
    private Map<String, Long> memory = new HashMap<String, Long>();

    private Long rightValue = 0L;

    private String leftKey = null;
    private String RightKey = null;

    /**
     * 数据库查询结果
     */
    private Map<String, List<Map<String, Object>>> afterDataBaseResult;
    private Map<String, List<Map<String, Object>>> beforeDataBaseResult;

    private String request;
    private String response;

    public JefCustomVisitor(Map<String, List<Map<String, Object>>> afterDataBaseResult, Map<String, List<Map<String, Object>>> beforeDataBaseResult, String request, String response) {
        this.afterDataBaseResult = afterDataBaseResult;
        this.beforeDataBaseResult = beforeDataBaseResult;
        this.request = request;
        this.response = response;
    }



    /**
     * 获取等号左边的计算结果
     * @return
     */
    public Long getLeftValue() {
        return memory.get(leftKey);
    }

    /**
     * 获取等号右边的值
     * @return
     */
    public Long getRightValue() {
        return memory.get(RightKey);
    }

    /**
     *  开始解析表达式，没有逻辑，默认实现
     * @param ctx
     * @return
     */
    @Override
    public Long visitProg(JefExpressionParser.ProgContext ctx) {
        return super.visitProg(ctx);
    }

    /**
     * 空白行处理，默认实现
     * @param ctx
     * @return
     */
    @Override
    public Long visitBlank(JefExpressionParser.BlankContext ctx) {
        return super.visitBlank(ctx);
    }

    /**
     * 带有等号（=）的完整表达式
     * @param ctx
     * @return
     */
    @Override
    public Long visitAssign(JefExpressionParser.AssignContext ctx) {
        return super.visitAssign(ctx);
    }

    /**
     * 等号左侧表达式处理
     * @param ctx
     * @return
     */
    @Override
    public Long visitLeftexpr(JefExpressionParser.LeftexprContext ctx) {

        String leftExpr = ctx.getText();
        Long value = visit(ctx.expr());
        if (leftKey == null) {
            leftKey = leftExpr;
        }
        memory.put(leftExpr, value);
        return value;
    }

    /**
     * 等号右侧表达式处理
     * @param ctx
     * @return
     */
    @Override
    public Long visitRightexpr(JefExpressionParser.RightexprContext ctx) {
        String rightExpr = ctx.getText();
        Long value = visit(ctx.expr());
        if (RightKey == null) {
            RightKey = rightExpr;
        }
        memory.put(RightKey, value);
        return value;
    }

    /**
     * 简单数字类型处理
     * @param ctx
     * @return
     */
    @Override
    public Long visitNumber(JefExpressionParser.NumberContext ctx) {

        return Long.valueOf(ctx.INT().getText());
    }

    /**
     * 出入参占位符处理,  走到这里的一定是{REQ/RESP?xxx}类型的,其中REQ代表着接口入参,RESP代表着接口出参
     * @param ctx
     * @return
     */
    @Override
    public Long visitJsonplaceholder(JefExpressionParser.JsonplaceholderContext ctx) {
        String key = ctx.JSONPLACEHOLDER().getText();
        if (key.startsWith("{R")) {
            return getNumberFromJSON(key);
        }
        if (memory.containsKey(key)) {
            return memory.get(key);
        }
        return super.visitJsonplaceholder(ctx);
    }

    public Long getNumberFromJSON(String key) {
        String jsonPathStr = "";
        if (key.startsWith("{REQ?")) {
            int index = key.indexOf("}");
            jsonPathStr = key.substring(5,index);
            return Long.valueOf(getDataFromJson(request, jsonPathStr).toString());
        }
        if (key.startsWith("{RESP?")) {
            int index = key.indexOf("}");
            jsonPathStr = key.substring(6,index);
            return Long.valueOf(getDataFromJson(response, jsonPathStr).toString());
        }
        return 0L;
    }

    /**
     * 数据库占位符处理,  走到这里的一定是{A/B?xxx.xx}类型的,其中A代表着接口执行后执行的sql结果,B代表着接口执行前执行的sql结果
     * @param ctx
     * @return
     */
    @Override
    public Long visitDbplaceholder(JefExpressionParser.DbplaceholderContext ctx) {
        String key = ctx.DBPLACEHOLDER().getText();
        String tableNameStr = "";
        if (key.startsWith("{A?")) {
            int index = key.indexOf("}");
            tableNameStr = key.substring(3,index);
            String[] strings = dealTableName(tableNameStr);
            return Long.valueOf(getDataFromDataBaseResult(afterDataBaseResult, strings[0], strings[1]).toString());
        }
        if (key.startsWith("{B?")) {
            int index = key.indexOf("}");
            tableNameStr = key.substring(3,index);
            String[] strings = dealTableName(tableNameStr);
            return Long.valueOf(getDataFromDataBaseResult(beforeDataBaseResult, strings[0], strings[1]).toString());
        }
        if (memory.containsKey(key)) {
            return memory.get(key);
        }
        return 0L;
    }

    /**
     * 从json中解析字段
     * @param jsonStr
     * @param jsonPathExpr
     * @return
     */
    public Object getDataFromJson(String jsonStr, String jsonPathExpr) {
        return JsonPath.read(jsonStr, jsonPathExpr);
    }
    /**
     * 根据表名和列名从数据库结果中获取数据
     * @param dataBaseResult
     * @param tableName
     * @param columnName
     * @return
     */
    public Object getDataFromDataBaseResult(Map<String, List<Map<String, Object>>> dataBaseResult, String tableName, String columnName) {

        List<Map<String, Object> > list = dataBaseResult.get(tableName.toUpperCase());
        for (Map<String, Object> map : list) {
            return map.get(columnName); // 找到一条即返回
        }
        return 0;
    }
    /**
     * 获取用户表名和列名
     * @param text
     * @return
     */
    public String[] dealTableName(String text) {

        String[] split = text.split("\\.");
        int pointCount = split.length;
        String[] tableAndColumn = new String[2];
        String tableName = "";
        int count = 0;
        for (int i=0; i<pointCount-1; i++) {
            count ++;
            tableName = tableName + split[i];
            if (count < pointCount-1) {
                tableName = tableName + ".";
            }
        }
        tableAndColumn[0] = tableName.toUpperCase();
        tableAndColumn[1] = split[pointCount-1].toUpperCase(); // 最后一个永远是数据库列名

        return tableAndColumn;
    }

    /**
     * 带有括号的子表达式处理
     * @param ctx
     * @return
     */
    @Override
    public Long visitParens(JefExpressionParser.ParensContext ctx) {
        return visit(ctx.expr());
    }

    /**
     * 乘除法运算
     * @param ctx
     * @return
     */
    @Override
    public Long visitMulDiv(JefExpressionParser.MulDivContext ctx) {

        Long left = visit(ctx.expr(0));
        Long right = visit(ctx.expr(1));

        if (ctx.op.getType() == JefExpressionParser.MUL) {
            return left * right;
        }
        return left / right; // 注意这里的整除，余数会被省略
    }

    /**
     * 加减法运算
     * @param ctx
     * @return
     */
    @Override
    public Long visitAddSub(JefExpressionParser.AddSubContext ctx) {
        Long left = visit(ctx.expr(0));
        Long right = visit(ctx.expr(1));

        if (ctx.op.getType() == JefExpressionParser.ADD) {
            return left + right;
        }
        return left - right;
    }
}
